package com.redsoft.spirit.config;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSubjectFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.redsoft.spirit.filter.StatelessAccessControlFilter;
import com.redsoft.spirit.realm.StatelessRealm;

/**
 * shiro配置类.
 * 
 * @author 杨雷
 * @version 1.0
 * @date 2017年3月21日 暂时不用了。没发现使用的价值所在。2017-06-26
 */
//@Configuration
public class ShiroConfiguration {

	@Bean
	public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
		ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
		factoryBean.setSecurityManager(securityManager);

		// 把要执行的所有过滤器都假如进来，key值下面要用。
		factoryBean.getFilters().put("statelessAuthc", statelessAuthcFilter());

		// 把要需要过滤的URL和指定的过滤器进行结合起来
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		filterChainDefinitionMap.put("/**", "statelessAuthc");
		factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

		return factoryBean;
	}

	/**
	 * shiro安全管理器: 主要是身份认证的管理，缓存管理，cookie管理， 所以在实际开发中我们主要是和SecurityManager进行打交道的
	 * 
	 * @return
	 */
	@Bean
	public DefaultWebSecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

		securityManager.setSubjectFactory(subjectFactory());
		securityManager.setSessionManager(sessionManager());
		securityManager.setRealm(statelessRealm());
		/*
		 * 禁用使用Sessions 作为存储策略的实现，但它没有完全地禁用Sessions
		 * 所以需要配合context.setSessionCreationEnabled(false);
		 */
		((DefaultSessionStorageEvaluator) ((DefaultSubjectDAO) securityManager.getSubjectDAO())
				.getSessionStorageEvaluator()).setSessionStorageEnabled(false);

		return securityManager;
	}

	/**
	 * Add.2.1 subject工厂管理器.
	 * 
	 * @return
	 */
	@Bean
	public DefaultWebSubjectFactory subjectFactory() {
		StatelessDefaultSubjectFactory subjectFactory = new StatelessDefaultSubjectFactory();
		return subjectFactory;
	}

	/**
	 * session管理器：
	 * sessionManager通过sessionValidationSchedulerEnabled禁用掉会话调度器，
	 * 因为我们禁用掉了会话，所以没必要再定期过期会话了。
	 * 
	 * @return
	 */
	@Bean
	public DefaultSessionManager sessionManager() {
		DefaultSessionManager sessionManager = new DefaultSessionManager();
		sessionManager.setSessionValidationSchedulerEnabled(false);
		return sessionManager;
	}

	/**
	 * 自己定义的realm.
	 * 
	 * @return
	 */
	@Bean
	public StatelessRealm statelessRealm() {
		StatelessRealm realm = new StatelessRealm();
		return realm;
	}

	/**
	 *访问控制器.
	 * 
	 * @return
	 */
	@Bean
	public StatelessAccessControlFilter statelessAuthcFilter() {
		StatelessAccessControlFilter statelessAuthcFilter = new StatelessAccessControlFilter();
		return statelessAuthcFilter;
	}

	/**
	 * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持;
	 * 
	 * @param securityManager
	 * @return
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);

		return authorizationAttributeSourceAdvisor;
	}

	/**
	 * 自动代理所有的advisor: 由Advisor决定对哪些类的方法进行AOP代理。
	 */
	@Bean
	public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
		daap.setProxyTargetClass(true);
		
		return daap;
	}
}